(function (context) {

    //带构造函数的对象继承
    var Extend = function (Parent, Child) {
        var F = function () { }; //声明一个空类
        F.prototype = Parent.prototype; //这个类的 prototype 指向 父类的 prototype
        Child.prototype = new F(); //创建空类的对象，并将空类对象赋值给 子类的 prototype
        Child.prototype.constructor = Child; //将子类的构造函数改回自身的构造函数（指向父类的 ptotitype 的时候，被改为父类的构造函数了）
        Child.uper = Parent.prototype; //添加一个指向父类的属性
        return Child;
    }
    //基础组件
    var RootComponent = function (props, rootComponentHtml) {
        //容器
        this.container = document.createElement("div");
        if (typeof props == "undefined") props = {};
        this.props = props;
        this.state = {};//内部保存的信息
        this.element = null; //保存组件生成的 dom
        this.componentchildren = []; //保存这个组件内创建的子组件对象
        this.updateHandler = [];//事件列表，用动态更新数据
        this.itemiomponentchildren = null;//列表组件才会用到的 保存子组件列
        this.rootComponentHtml = rootComponentHtml; //组件待解析的内容
        this.parentNode = null;//相当一个容器


        if (typeof RootComponent._inited_ == "undefined") {
            //更新组件
            RootComponent.prototype.update = function (props) {

                if (this.updateHandler.length > 0) {
                    for (var fnkey in this.updateHandler) {
                        var fn = this.updateHandler[fnkey].bind(this);
                        fn(this);
                    }
                }
                //处理显隐状态
                this.handerComif();
            }
            //更新组件
            RootComponent.prototype.componentUpdate = function (props) {
                if (typeof props == "undefined") props = {};
                this.props = props;

                //console.log(this)
                //console.log(this.itemiomponentchildren)
                //对于 列表组件 进行特殊处理，是列表组件的，重新“创建” 而不只是刷新
                if (this.itemiomponentchildren instanceof Array) {
                    var tempnode = this.getElement();
                    var temelement = [];
                    //console.log(this.parentNode);
                    //这里先给它清空现有的
                    this.parentNode.innerHTML = "";
                    for (var key = tempnode.length; key > 0; key--) {
                        try {
                            temelement.push(tempnode[0])
                            this.parentNode.appendChild(tempnode[0]);
                        }
                        catch (e) {
                            break;
                        }
                    }
                    this.element = temelement;
                }
                else {
                    this.update();
                }
            }
            //初始化后执行
            RootComponent.prototype.componentDidMount = function () {

            }
            //被卸载时执行
            //TODO 暂时不懂该在什么地方执行，预留着
            RootComponent.prototype.componentWillUnmount = function () {

            }
            //返回 html
            RootComponent.prototype.render = function () {
                return this.rootComponentHtml;
            }
            //更新 state
            RootComponent.prototype.setState = function (state) {

                //是 function 的话作为回调使用
                if (typeof state === "function") {
                    state = state(this.state)
                }

                if (typeof state === "object") {
                    for (var key in state) {
                        var statevalue = state[key]
                        if (typeof statevalue == 'undefined') statevalue = "";
                        this.state[key] = statevalue;
                    }
                }
                //更新 element
                this.update();
                //var tempnode = this.getElement();

                //this.element.parentNode.replaceChild(tempnode, this.element);
                // this.element = tempnode;
            }
            //创建子组件
            RootComponent.prototype.createComponent = function (comname, props) {
                var func = new Function("props", "return new " + comname + "(props)");
                var component = func(props);
                return component;
            }
            //处理 text 节点内容
            RootComponent.prototype.handlerTextChild = function (node) {
                var func = JSTemplate.getFunc(node.nodeValue)
                var nodevalue = func.call(this, this, this.props);
                node.nodeValue = nodevalue;


                var updatefn = function (name, func, node) {
                    return function (comobj) {
                        var _this = comobj;
                        var _name = name;
                        var _func = func;
                        var _node = node;
                        var nodevalue = _func.call(_this, _this, _this.props);
                        _node.nodeValue = nodevalue;
                    }
                }
                updatefn = updatefn.bind(this);
                var fn = updatefn(name, func, node).bind(this);
                fn(this);
                this.updateHandler.push(fn);
            }
            //处理子组件
            RootComponent.prototype.handlerComponentChild = function (node) {
                var comname = "";
                var comprops = {};
                //是判断是否有包含内容，有的话，将内容转成 dom 之后再返回 children，然后这个children 将作为一个参数传递到 这个组件，至于这个组将要将子内容放到哪里，那是另外一回事
                if (node.childNodes.length > 0) {
                    var comchildren = this.handlerChild(node.childNodes);
                    //这里能做么做comchildren[0] 前提是 这个 componentchildren 标签没有兄弟标签,即 如果要给 组件加上 children 的话，最外层必须是一个大标签
                    comprops["component-children"] = comchildren[0];
                }

                var compropsfns = [];


                var attrnames = node.getAttributeNames();
                for (var key in attrnames) {
                    var name = attrnames[key];
                    //除了组件名称，其余的均当作对象的值来处理

                    var value = node.getAttribute(name);
                    // 指定 com-name 属性的值为组件 名称
                    if (name === 'com-name') {
                        comname = value;
                    }
                    else {

                        value = value.replace("{", "").replace("}", "");
                        var func = new Function("return " + value);

                        func = func.bind(this)
                        var nodevalue = func();

                        comprops[name] = nodevalue;

                        //保存获取 props 的方法
                        var updatefn = function (name, func) {

                            return function (comobj) {
                                var _this = comobj;
                                var _name = name;
                                var _fun = func;
                                var nodevalue = _fun.call(_this);
                                return { name: _name, value: nodevalue }
                            }
                        }
                        updatefn = updatefn.bind(this);
                        var fn = updatefn(name, func).bind(this);
                        compropsfns.push(fn);

                    }
                }

                //创建并替换子节点
                var com = this.createComponent(comname, comprops);
                com.parentNode = node.parentNode;
                var htmlnode = com.handerRender();

                this.componentchildren.push(com);

                var updatefn = function (com, compropsfns) {

                    return function (comobj) {
                        var _this = comobj;
                        var _com = com;
                        var _compropsfns = compropsfns;

                        var _props = {};
                        if (_compropsfns.length > 0) {
                            for (var _index = 0; _index < compropsfns.length; _index++) {
                                var compropsinfo = compropsfns[_index](this);
                                _props[compropsinfo.name] = compropsinfo.value;
                            }
                        }

                        _com.componentUpdate(_props);//子组件只需要操作更新
                    }
                }
                updatefn = updatefn.bind(this);
                var fn = updatefn(com, compropsfns).bind(this);
                //fn(this);
                this.updateHandler.push(fn);

                return htmlnode;
            }

            //处理children dom  (children dom 的值来源于 父组件 )
            RootComponent.prototype.handlerChildrenChild = function (node) {


                var componentchildren = this.props["component-children"];
                if (typeof componentchildren === 'object') {
                    //这里能做么做 前提是 这个 componentchildren 标签没有兄弟标签,即 如果要给 组件加上 children 的话，最外层必须是一个大标签
                    node.parentNode.replaceChild(componentchildren, node);
                }
                else
                    node.remove();



            }
            //处理普通 dom 节点
            RootComponent.prototype.handlerNormalDOMChild = function (node) {
                var attrnames = node.getAttributeNames();
                for (var key in attrnames) {
                    var name = attrnames[key];
                    //是 on- 开头说明是事件，需要做处理
                    if (name.indexOf("on-") > -1) {
                        var attrvalue = node.getAttribute(name);

                        var func = new Function("return " + attrvalue.replace("{", "").replace("}", ""));
                        func = func.call(this)
                        if (typeof func == 'function') node.addEventListener(name.split('-')[1], func)

                        node.removeAttribute(name)
                    }
                    //用于判断显示隐藏
                    else if (name.indexOf("com-if") > -1) {

                        var attrvalue = node.getAttribute(name);
                        if (attrvalue.length > 0) {
                            var func = JSTemplate.getFunc(attrvalue)

                            var updatefn = function (name, func, node) {
                                return function (comobj) {
                                    var _this = comobj;
                                    var _name = name;
                                    var _func = func;
                                    var _node = node;

                                    var _attrvalue = func.call(_this, _this, _this.props);
                                    if (_attrvalue == 'false') {
                                        _node.style.setProperty("display", "none");
                                    }
                                    else {
                                        _node.style.removeProperty("display");
                                    }
                                }
                            }
                            updatefn = updatefn.bind(this);
                            var fn = updatefn(name, func, node).bind(this);
                            fn(this);
                            this.updateHandler.push(fn);

                        }
                        node.removeAttribute(name)
                    }
                    //非 事件 的属性，只需要解析赋值既可以
                    else {

                        var attrvalue = node.getAttribute(name);
                        if (attrvalue.length > 0) {
                            var func = JSTemplate.getFunc(attrvalue)

                            var updatefn = function (name, func, node) {
                                return function (comobj) {
                                    var _this = comobj;
                                    var _name = name;
                                    var _func = func;
                                    var _node = node;

                                    var _attrvalue = func.call(_this, _this, _this.props);
                                    _node[_name] = _attrvalue;
                                    _node.removeAttribute(_name);
                                    _node.setAttribute(_name, _attrvalue);

                                }
                            }
                            updatefn = updatefn.bind(this);
                            var fn = updatefn(name, func, node).bind(this);
                            fn(this);
                            this.updateHandler.push(fn);

                        }
                    }
                }
            }


            RootComponent.prototype.handlerChild = function (children) {
                for (var index = 0; index < children.length; index++) {
                    var node = children[index];
                    //普通内容节点，解析内容处理
                    if (node.nodeName == '#text' && node.nodeValue.length > 0) {

                        this.handlerTextChild(node);
                    }
                    //用户组件处理
                    else if (node.nodeName == 'COMPONENT') {
                        var htmlnode = this.handlerComponentChild(node);
                        if (htmlnode.length > 0) {
                            for (var htmlnodeindex = 0; htmlnodeindex < htmlnode.length; htmlnodeindex++) {
                                node.parentNode.appendChild(htmlnode[htmlnodeindex])
                            }
                            node.remove();
                            return children;
                        }
                        else {
                            try {
                                node.parentNode.replaceChild(htmlnode, node);
                            }
                            catch (e) {
                                //console.log(e)
                            }
                        }

                    }
                    //如果是子内容（我们规定 使用 CHILDREN 作为节点名称的，将会被传进来的  component-children 覆盖）
                    else if (node.nodeName == 'CHILDREN') {
                        this.handlerChildrenChild(node)
                    }
                    //非 组件 dom 节点解析
                    else {
                        this.handlerNormalDOMChild(node);
                    }
                    if (node.childNodes.length > 0) {
                        node.childNodes = this.handlerChild(node.childNodes)
                    }
                }
                return children;
            }

            //渲染（返回dom）
            RootComponent.prototype.getElement = function () {

                var templatecontent = this.render();
                if (typeof templatecontent == "string") {
                    //var func = JSTemplate.getFunc(templatecontent)
                    //var html = func.call(this, this, props);
                    /*
                        将 html 放到一个 dom 容器中，然后再解析里面的事件标识
                    */
                    this.container.innerHTML = templatecontent;
                    var nodes = this.handlerChild(this.container.childNodes)
                    return nodes;
                }
                else {
                    if (this.itemiomponentchildren != null) {
                        for (var key = 0; key < this.itemiomponentchildren.length; key++) {
                            this.itemiomponentchildren[key].componentWillUnmount();
                        }
                    }

                    this.itemiomponentchildren = templatecontent;
                    for (var key in templatecontent) {

                        //console.log(templatecontent[key]);
                        var tempchildren = null;
                        if (templatecontent[key].element != null) {
                            //不为null 说明是现有的对象，刷新组件即可
                            templatecontent[key].componentUpdate();
                            tempchildren = templatecontent[key].element;
                        }
                        else {
                            //新创建的组件要调用渲染
                            tempchildren = templatecontent[key].handerRender();
                        }
                        for (var tempchildrenkey = 0; tempchildrenkey < tempchildren.length; tempchildrenkey++) {
                            this.container.appendChild(tempchildren[tempchildrenkey]);
                        }

                    }
                    return this.container.childNodes;
                }

            }
            //根据传进来的 com-if 处理组件自己的 显示状态
            RootComponent.prototype.handerComif = function () {
                if (typeof this.props["com-if"] != "undefined") {
                    for (var key in this.element) {
                        if (this.props["com-if"] == true)
                            this.element[key].style.removeProperty("display")
                        else if (this.props["com-if"] == false)
                            this.element[key].style.setProperty("display", "none")
                    }
                }
            }

            //渲染（返回dom）
            RootComponent.prototype.handerRender = function () {
                var element = this.getElement();
                var temelement = [];
                for (var key = 0; key < element.length; key++) {
                    temelement.push(element[key]);
                }
                this.element = temelement;
                //初始化完成回调
                this.componentDidMount();
                //处理显隐状态
                this.handerComif();
                return this.element;
            }
            //销毁
            RootComponent.prototype.destroy = function () {
                this.componentWillUnmount();
                for (var key = 0; key < this.componentchildren.length; key++) {
                    this.componentchildren[key].destroy();
                }
                if (this.itemiomponentchildren != null) {
                    for (var key = 0; key < this.itemiomponentchildren.length; key++) {
                        this.itemiomponentchildren[key].destroy();
                    }
                }
                for (var key = 0; key < this.updateHandler.length; key++) {
                    this.updateHandler[key] = null;
                }

            }
            RootComponent._inited_ = true;
            //页面离开前触发 组件销毁前事件
            context.addEventListener("beforeunload",this.destroy);
        }
    }


    var ItemComponent = Extend(RootComponent, function (ItemComponentHtml, index, item, data) {
        RootComponent.call(this, {}, ItemComponentHtml);
        this.Index = index;
        this.Item = item;
        this.Data = data;

        if (typeof ItemComponent._inited_ == "undefined") {

            ItemComponent.prototype.componentWillUnmount = function () {
                for (var key = 0; key < this.componentchildren.length; key++) {
                    this.componentchildren[key].destroy();
                    //this.componentchildren[key] = null;
                }
            }
            //覆盖获取模板内容的方法
            ItemComponent.prototype.render = function () {
                return this.rootComponentHtml;
            }
            ItemComponent._inited_ = true;
        }

    }); //继承 基础组件

    //根 组件，用于渲染入口，默认不需要传值（作为根组件，也没有必要传值，如果是需要传值的组件，则再包装一层组件即可，）
    //直接传入根组件 的 html 写法
    var BaseComponent = Extend(RootComponent, function (props, rootComponentHtml) {
        RootComponent.call(this, props, rootComponentHtml);
        if (typeof BaseComponent._inited_ == "undefined") {

            //创建  列表 item 的方法 fnCreateItemComponent 为 function 提供 index,item 两个参数，返回 一个 ItemComponent 对象
            BaseComponent.prototype.createItem = function (datalist, fnCreateItemComponent) {
                var coms = [];
                for (var index in datalist) {
                    var tempcom = null;
                    var item = datalist[index]
                    if (this.itemiomponentchildren != null) {

                        for (var key =0;key< this.itemiomponentchildren.length ; key++) {
                            if (item == this.itemiomponentchildren[key].Item) {
                                tempcom = this.itemiomponentchildren[key];
                                this.itemiomponentchildren.splice(key, 1);
                                tempcom.Index = index;
                                break;
                            }
                        }
                    }

                    if (tempcom == null)
                        tempcom = fnCreateItemComponent.call(this, index, item);
                    //tempcom =  this.createItemComponent("<component com-name=Item value={this.Index+':'+this.Item.value}></component>", index, this.props.list[index]);

                    coms.push(tempcom);
                }

                return coms;
            }


            //创建item组件(列表数据用到)
            BaseComponent.prototype.createItemComponent = function (html, index, item, data) {
                return new ItemComponent(html, index, item, data);
            }

            BaseComponent._inited_ = true;
        }

    }); //继承 基础组件

    var DOMRender = function (rootComponentHtml, rootnode) {
        var component = new BaseComponent({}, rootComponentHtml);
        var tempchildren = component.handerRender();
        for (var key = 0; key < tempchildren.length; key++) {
            rootnode.appendChild(tempchildren[key]);
        }
        return component;
    }

    //对外开放
    context.MyReact = {
        Extend: Extend,
        BaseComponent: BaseComponent,
        DOMRender: DOMRender
    }

})(window)
